:- module(mode_analyser).
:- export reset / 1.
:- export result_body / 2.
:- export result_body / 1.
:- export analyse_body / 2.
:- export reset / 0.
:- export result / 1.
:- export result / 0.
:- export weave_analyse_mode_code / 6.
:- export analyse / 1.
:- comment(summary, "Instrumentation based mode analyser").
:- comment(author, "Andrew Cheadle").
:- comment(date, "$Date: 2003/12/09 18:52:10 $").
:- comment(copyright, "Imperial College London and Parc Technologies Ltd").
:- comment(status, prototype).
:- comment(desc, html("<P>\n    The mode_analyser library is a tool that assists in the determination of\n    the mode/1 directive for predicate definitions. This directive informs\n    the compiler that the arguments of the specified predicate will always \n    have the corresponding form when the predicate is called. The compiler \n    utilises this information during compilation of the predicate in order\n    to generate more compact and/or faster code. Specifying the mode of a \n    predicate that has already been compiled has no effect, unless it is \n    recompiled. If the specified procedure does not exist, a local\n    undefined procedure is created.\n</P><P>\n    The mode analyser inserts instrumentation into the clause definitions of\n    predicates during compilation in order to record mode usage of each \n    predicate argument. The code should then be run (as many times as is\n    necessary to capture the most common invocations of each predicate \n    undergoing analysis). Finally, the results of the analysis are requested\n    and the suggested mode annotations for each predicate are displayed.\n</P><P>\n    NOTE: It is imperative to understand that the results of mode analysis \n    are merely suggestions for the invocation modes of a predicate based on \n    runtime information. If there are potential predicate invocation modes \n    that were not exercised during runtime, the tool is unable to account \n    for them in its analysis. For the mode specifier '-' the mode analyser\n    does not determine whether the variable occurs in any other argument\n    (i.e. is aliased), this must be manually verified. \n    In summary, the programmer must verify that the suggested modes are correct \n    before using the directive in the code.  If the instantiation of the \n    predicate call violates its mode declaration, no exception is raised and \n    its behaviour is undefined.\n</P><P>\n\tThe usage is as follows:\n\t<OL>\n\t<LI>Load the mode_analyser library\n\t<PRE>\n\t?- lib(mode_analyser).\n\t</PRE>\n\t<LI>Compile your program with the mode analyser compiler\n    <PRE>\n\t?- mode_analyser:analyse(my_program).\n\t</PRE>\n\t<LI>Run the query for which you wish to generate mode analysis data\n\t<PRE>\n\t?- my_query(X,Y,Z).\n\t</PRE>\n\t<LI>Generate the results for the module into which the program\n        was compiled.\n\t<PRE>\n\t?- mode_analyser:result(my_program_module).\n\t</PRE>\n</P><P>\n\tLimitations to be resolved shortly: \n\t<OL>\n    <LI>A future enhancement will enable the insertion of the suggested \n    (or programmer ammended) mode/1 directives for each predicate\n    definition into the source code.\n    </OL>\n</P>")).
:- comment(analyse / 1, [summary : "Compile a file, inserting invocation mode analysis \n   instrumentation for each predicate definition.", args : ["File" : "Atom or string"], amode : analyse(+), resat : no, exceptions : [5 : "File is not an atom or string"], see_also : [result / 0, result / 1, reset / 0], desc : html("<P>    \n   The mode analyser is a variant of the ECLiPSe that inserts \n   instrumentation into the clause definitions of predicates\n   (defined in the named file) during compilation in order to record mode \n   usage of each predicate argument. The code is then run as many times \n   as is necessary to capture the most common invocations of each \n   predicate undergoing analysis. Finally, the results are analysed, \n   using <TT>mode_analyser:result/0</TT>, to produce suggested mode/1 \n   directives for each predicate.\n   </P><P>\n   The mode/1 directive informs the compiler that the arguments of the \n   specified predicate will always have the corresponding form when the \n   predicate is called.  The compiler utilises this information during \n   compilation of the predicate in order to generate more compact and/or \n   faster code. Specifying the mode of a predicate that has already been \n   compiled has no effect, unless it is recompiled. If the specified \n   procedure does not exist, a local undefined procedure is created.\n   </P><P>\n   NOTE: It is imperative to understand that the results of mode analysis \n   are merely suggestions for the invocation modes of a predicate based on \n   runtime information. If there are potential predicate invocation modes \n   that were not exercised during runtime, the tool is unable to account \n   for them in its analysis. For the mode specifier '-' the mode analyser\n   does not determine whether the variable occurs in any other argument\n   (i.e. is aliased), this must be manually verified. \n   In summary, the programmer must verify that the suggested modes are correct \n   before using the directive in the code.  If the instantiation of the \n   predicate call violates its mode declaration, no exception is raised and \n   its behaviour is undefined."), eg : "\n   [eclipse 1]: mode_analyser:analyse('queens_gfc.pl').\n   queens_gfc.pl compiled traceable 13920 bytes in 0.10 seconds\n\n   Yes (0.10s cpu)"]).
:- comment(reset / 0, [summary : "Reset the mode analysis results for predicates compiled \n   into the calling context module.", args : [], fail_if : no, resat : no, exceptions : [4 : "Calling context module is not instantiated"], desc : html("<P>\n   This predicate erases all mode analysis data for every predicate that \n   has been compiled into the calling context module using the mode \n   analysis compiler.  The predicate is a tool and as such can be \n   invoked for an arbitrary module using <TT>mode_analyser:reset@Module</TT>."), eg : "\n   [eclipse 6]: mode_analyser:reset@eclipse.\n\n   Yes (0.00s cpu)", see_also : [analyse / 1, result / 0, result / 1]]).
:- comment(result / 0, [summary : "Produce the mode analysis results for predicates \n   compiled into the calling context module.", args : [], fail_if : "No predicates have been compiled with the mode analyser \n   into the calling context module.", exceptions : [4 : "Calling context module is not instantiated"], resat : no, see_also : [analyse / 1, result / 1, reset / 0], desc : html("<P>\n   This predicate displays the suggested invocation modes for each \n   predicate compiled using the mode analyser into the calling context module. \n   The suggested mode annotations can be passed to the mode/1 directive for \n   the associated predicate. The predicate is a tool and as such can be \n   invoked for an arbitrary module using <TT>mode_analyser:result@Module</TT>.\n   </P><P>\n   The possible argument modes produced for each argument of each \n   predicate are: \n   </P><P><PRE>\n   +   The argument is instantiated, i.e. it is not a variable.\n   </PRE></P><P><PRE>\n   ++  The argument is ground.\n   </PRE></P><P><PRE>\n   -   The argument is not instantiated, it must be a free variable without \n       any constraints, especially it must not occur in any other argument \n       and it cannot be a suspending variable. \n   </PRE></P><P><PRE>\n   ?   The mode is not known or it is neither of the above ones.\n   </PRE></P><P>\n   NOTE: It is imperative to understand that the results of mode analysis \n   are merely suggestions for the invocation modes of a predicate based on \n   runtime information. If there are potential predicate invocation modes \n   that were not exercised during runtime, the tool is unable to account \n   for them in its analysis. For the mode specifier '-' the mode analyser\n   does not determine whether the variable occurs in any other argument\n   (i.e. is aliased), this must be manually verified. \n   In summary, the programmer must verify that the suggested modes are correct \n   before using the directive in the code.  If the instantiation of the \n   predicate call violates its mode declaration, no exception is raised and \n   its behaviour is undefined."), eg : "\n   [eclipse 2]: nqueens(8, Qs).\n   L = [1, 5, 8, 6, 3, 7, 2, 4]\n   Yes (0.00s cpu, solution 1, maybe more) ?\n\n   ...\n   ...\n\n   Yes (0.10s cpu)\n\n   [eclipse 5]: mode_analyser:result.\n           nqueens(++, -)\n           noattack(?, ?)\n           safe(+)\n           noattack(?, +, ++)\n\n   Yes (0.00s cpu)"]).
:- comment(result / 1, [summary : "Produce the mode analysis results for predicates\n   compiled into the calling context module.", args : ["OptionList" : "List of Name:Value pairs"], amode : result(+), exceptions : [4 : "Calling context module is not instantiated"], fail_if : "No predicates have been compiled with the mode analyser \n   into the calling context module.", resat : no, exceptions : [4 : "Calling context module is not instantiated"], see_also : [analyse / 1, result / 0, reset / 0], desc : html("<P>\n   This predicate displays the suggested invocation modes for each predicate \n   compiled using the mode analyser into the calling context module. \n   The suggested mode annotations can be passed to the mode/1 directive for \n   the associated predicate. The predicate is a tool and as such can be \n   invoked for an arbitrary module using <TT>mode_analyser:result@Module</TT>.\n   </P><P>\n   OptionList may contain the following options:\n   <DL><DT>\n   <PRE>verbose (default:off)</PRE>\n   <DD>If set to 'on', the mode analyser will print details of argument \n   invocation modes for each argument of every predicate compiled into \n   the module with the mode analyser.\n   </DL></P></P><P>\n   The possible argument modes produced for each argument of each \n   predicate are: \n   </P><P><PRE>\n   +   The argument is instantiated, i.e. it is not a variable.\n   </PRE></P><P><PRE>\n   ++  The argument is ground.\n   </PRE></P><P><PRE>\n   -   The argument is not instantiated, it must be a free variable without \n       any constraints, especially it must not occur in any other argument \n       and it cannot be a suspending variable. \n   </PRE></P><P><PRE>\n   *   The argument is an attributed variable that may have constraints \n       or is a suspending variable. This detail is not a valid argument mode\n       to the mode/1 directive and is printed merely for interest. As a result\n       the actual argument mode will appear as '?'.\n   </PRE></P><P><PRE>\n   ?   The mode is not known or it is neither of the above ones.\n   </PRE></P><P>\n   NOTE: It is imperative to understand that the results of mode analysis \n   are merely suggestions for the invocation modes of a predicate based on \n   runtime information. If there are potential predicate invocation modes \n   that were not exercised during runtime, the tool is unable to account \n   for them in its analysis. For the mode specifier '-' the mode analyser\n   does not determine whether the variable occurs in any other argument\n   (i.e. is aliased), this must be manually verified. \n   In summary, the programmer must verify that the suggested modes are correct \n   before using the directive in the code.  If the instantiation of the \n   predicate call violates its mode declaration, no exception is raised and \n   its behaviour is undefined."), eg : "\n   [eclipse 2]: nqueens(8, Qs).\n   L = [1, 5, 8, 6, 3, 7, 2, 4]\n   Yes (0.00s cpu, solution 1, maybe more) ?\n   ...\n   ...\n   Yes (0.10s cpu)\n   [eclipse 5]: mode_analyser:result([verbose:on]).\n\n   Mode analysis for eclipse : nqueens / 2:\n        Results for argument 1:\n                -: 0    *: 0    +: 0    ++: 1\n        Results for argument 2:\n                -: 1    *: 0    +: 0    ++: 0\n\n        nqueens(++, -)\n\n   Mode analysis for eclipse : noattack / 2:\n        Results for argument 1:\n                -: 0    *: 8    +: 0    ++: 0\n        Results for argument 2:\n                -: 0    *: 0    +: 7    ++: 1\n\n        noattack(?, ?)\n\n   Mode analysis for eclipse : safe / 1:\n        Results for argument 1:\n                -: 0    *: 0    +: 8    ++: 0\n\n        safe(+)\n\n   Mode analysis for eclipse : noattack / 3:\n        Results for argument 1:\n                -: 0    *: 28   +: 0    ++: 0\n        Results for argument 2:\n                -: 0    *: 0    +: 28   ++: 0\n        Results for argument 3:\n                -: 0    *: 0    +: 0    ++: 28\n\n        noattack(?, +, ++)\n\n   Yes (0.00s cpu)"]).
:- comment(weave_analyse_mode_code / 6, hidden).
:- comment(reset / 1, hidden).
:- comment(result_body / 2, hidden).
:- comment(result_body / 1, hidden).
:- comment(analyse_body / 2, hidden).
